﻿using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using UnityEditor.Animations;
using System.Text.RegularExpressions;

class ProcessModel : AssetPostprocessor
{

    List<string> fbxAnimNames = new List<string> { "Idle", "Run", "Attack", "Skill", "Dead" };

    void OnPostprocessModel(GameObject input)
    {
        // 只处理名为"Enemy2b"的模型
        //if (input.name != "Enemy2b")
        //    return;
        var modelName = input.name;

        Debug.Log("Process Model!" + input.name);

        // 取得导入模型的相关信息
        ModelImporter importer = assetImporter as ModelImporter;

        // 从工程中将该模型读出来
        GameObject tar = AssetDatabase.LoadAssetAtPath<GameObject>(importer.assetPath);

        // 将这个模型创建为prefab
        var prefabPath = "Assets/Resources/Prefabs/Actor/" + modelName + ".prefab";
        GameObject prefab = PrefabUtility.SaveAsPrefabAsset(tar, prefabPath); //PrefabUtility.CreatePrefab("Assets/Prefabs/Enemy2c.prefab", tar);
        // 设置Prefab的tag
        prefab.tag = "Actor";
        var animator = prefab.GetComponent<Animator>();
        if (animator != null)
        {
            prefab.AddComponent<Animator>();
        }
        //RuntimeAnimatorController.
        //animator.runtimeAnimatorController=
        //animator.avatar=ta
        // 查找碰撞模型
        //foreach (Transform obj in prefab.GetComponentsInChildren<Transform>())
        //{
            //if (obj.name == "col")
            //{
            //    // 取消碰撞模型的显示
            //    MeshRenderer r = obj.GetComponent<MeshRenderer>();
            //    r.enabled = false;

            //    // 添加Mesh碰撞体
            //    if (obj.gameObject.GetComponent<MeshCollider>() == null)
            //        obj.gameObject.AddComponent<MeshCollider>();

            //    // 设置碰撞体的tag
            //    obj.tag = "Enemy";
            //}
        //}

        // 设置刚体
        //Rigidbody rigid = prefab.AddComponent<Rigidbody>();
        //rigid.useGravity = false;
        //rigid.isKinematic = true;
        //prefab.AddComponent<CharacterController>();
        // 为prefab添加声音组件
        //prefab.AddComponent<AudioSource>();
        

        // 获得子弹的prefab
        //GameObject rocket = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/EnemyRocket.prefab");

        // 获得爆炸效果的prefab
        //GameObject fx = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/FX/Explosion.prefab");

        // 为prefab添加角本
        //SuperEnemy enemy = prefab.AddComponent<SuperEnemy>();
        // 设置角本的默认参数
        //enemy.m_life = 50;
        //enemy.m_point = 50;
        //enemy.m_rocket = rocket.transform;
        //enemy.m_explosionFX = fx.transform;
    }

    [MenuItem("Tools/ExtractAnim")]
    static void ExtractAnimClipTool()
    {
        Object[] objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);

        //var fbxPaths = objs.Select(x =>)
        //                    .Where(x => x.ToLower().EndsWith("fbx"));
        foreach (var x in objs)
        {
            var filePath = AssetDatabase.GetAssetPath(x);
            if (filePath.ToLower().EndsWith("fbx"))
            {
                //Debug.Log(filePath);
                ProcessFbx(filePath);
            }
        }
    }

    //[MenuItem("Tools/AllModelAnim")]
    static void ExtractAllModelAnim()
    {
        //Selection.GetFiltered(typeof)
        string[] strs = Selection.assetGUIDs;
        string path = AssetDatabase.GUIDToAssetPath(strs[0]);
        Debug.Log(path);
        string[] files = Directory.GetFiles(path);
        foreach (var filename in files)
        {
            var filename2 = filename.Replace("\\", "/");
            if (filename2.ToLower().EndsWith("fbx"))
            {
                Debug.Log(filename2);
                ProcessFbx(filename2);
            }
        }
    }

    [MenuItem("Tools/RenameAssetName")]
    static void RenameAssetName()
    {
        string[] strs = Selection.assetGUIDs;
        string path = AssetDatabase.GUIDToAssetPath(strs[0]);
        Debug.Log(path);
        string[] files = Directory.GetFiles(path);
        foreach (var filename in files)
        {
            var filename2 = filename.Replace("\\", "/");
            if (filename2.ToLower().EndsWith("fbx"))
            {
                Debug.Log(filename2);
                var newFileName = filename2.Replace("#", "");
                newFileName = newFileName.Replace(" ", "");
                var regex = new Regex("\\d+");
                Debug.Log(newFileName);
                newFileName = regex.Replace(newFileName, "", 1);
                Debug.Log(filename2);
                Debug.Log(newFileName);
                Debug.Log("-----------------------");
                newFileName = Path.GetFileNameWithoutExtension(newFileName);
                Debug.Log(newFileName);
                AssetDatabase.RenameAsset(filename, newFileName + ".fbx");
            }
        }
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    [MenuItem("Tools/CopyAssetsName")]
    static void CopyAssetsName()
    {
        string[] strs = Selection.assetGUIDs;
        string path = AssetDatabase.GUIDToAssetPath(strs[0]);
        Debug.Log(path);
        string[] files = Directory.GetFiles(path);
        var content = "";
        foreach (var filename in files)
        {
            if (filename.ToLower().EndsWith("fbx"))
            {
                var filename2 = Path.GetFileNameWithoutExtension(filename);
                content += filename2 + "\n";
            }
        }
        Debug.Log(content);
    }

    static void ProcessFbx(string fbxPath)
    {
        if(Path.GetExtension(fbxPath)!=".fbx")
        {
            Debug.LogError("这不是一个fbx");
            return;
        }
        var filePath = "Assets" + "/AnimClip";
        Debug.Log(filePath);
        if(!Directory.Exists(filePath))
        {
            Directory.CreateDirectory(filePath);
        }
        var fileName = Path.GetFileNameWithoutExtension(fbxPath);
        Object[] assets = AssetDatabase.LoadAllAssetsAtPath(fbxPath);
        List<AnimationClip> clips = new List<AnimationClip>();
        var fileAnimPath = filePath + "/" + fileName;
        if (Directory.Exists(fileAnimPath))
        {
            Directory.Delete(fileAnimPath, true);
        }
        Directory.CreateDirectory(fileAnimPath);
        Dictionary<string,bool> animCount = new Dictionary<string, bool> {
            { "Idle", true }, { "Run", true }, { "Attack", true }, { "Skill", true },
            { "Dead", true },{ "HurtLand",true},
        };
        foreach (var clip in assets)
        {
            if (clip is AnimationClip)
            {
                if (!clip.name.Contains("__preview__"))
                {
                    var tempName = clip.name;
                    if (tempName.Contains("Idle"))
                    {
                        if (animCount["Idle"])
                        {
                            var clipAnim = (AnimationClip)clip;
                            var clone = Object.Instantiate<AnimationClip>(clipAnim);
                            var clipName = "Idle";
                            animCount["Idle"] = false;
                            var clipFileName = fileAnimPath + "/" + clipName + ".anim";
                            AnimationClipSettings clipSetting = AnimationUtility.GetAnimationClipSettings(clone);
                            clipSetting.loopTime = !clone.isLooping;
                            AnimationUtility.SetAnimationClipSettings(clone, clipSetting);
                            AssetDatabase.CreateAsset(clone, clipFileName);
                            continue;
                        }
                    }
                    if (tempName.Contains("Run"))
                    {
                        if (animCount["Run"])
                        {
                            var clone = Object.Instantiate<AnimationClip>((AnimationClip)clip);
                            var clipName = "Run";
                            animCount["Run"] = false;
                            var clipFileName = fileAnimPath + "/" + clipName + ".anim";
                            AnimationClipSettings clipSetting = AnimationUtility.GetAnimationClipSettings(clone);
                            clipSetting.loopTime = !clone.isLooping;
                            AnimationUtility.SetAnimationClipSettings(clone, clipSetting);
                            AssetDatabase.CreateAsset(clone, clipFileName);
                            continue;
                        }
                    }
                    if (tempName.Contains("Attack"))
                    {
                        if (animCount["Attack"])
                        {
                            var clone = Object.Instantiate<AnimationClip>((AnimationClip)clip);
                            var clipName = "Attack";
                            animCount["Attack"] = false;
                            var clipFileName = fileAnimPath + "/" + clipName + ".anim";
                            AssetDatabase.CreateAsset(clone, clipFileName);
                            continue;
                        }

                    }
                    if (tempName.Contains("Skill"))
                    {
                        if (animCount["Skill"])
                        {
                            var clone = Object.Instantiate<AnimationClip>((AnimationClip)clip);
                            var clipName = "Skill";
                            animCount["Skill"] = false;
                            var clipFileName = fileAnimPath + "/" + clipName + ".anim";
                            AssetDatabase.CreateAsset(clone, clipFileName);
                            continue;
                        }

                    }
                    if (tempName.Contains("Dead"))
                    {
                        if (animCount["Dead"])
                        {
                            var clone = Object.Instantiate<AnimationClip>((AnimationClip)clip);
                            var clipName = "Dead";
                            animCount["Dead"] = false;
                            var clipFileName = fileAnimPath + "/" + clipName + ".anim";
                            AssetDatabase.CreateAsset(clone, clipFileName);
                            continue;
                        }

                    }
                    if (tempName.Contains("HurtLand"))
                    {
                        if (animCount["HurtLand"])
                        {
                            var clone = Object.Instantiate<AnimationClip>((AnimationClip)clip);
                            var clipName = "HurtLand";
                            animCount["HurtLand"] = false;
                            var clipFileName = fileAnimPath + "/" + clipName + ".anim";
                            AssetDatabase.CreateAsset(clone, clipFileName);
                            continue;
                        }
                    }
                }
            }
        }
        foreach (var v in animCount)
        {
            if (v.Value)
            {
                Directory.Delete(fileAnimPath, true);
                break;
            }
        }
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    static void ProcessFbxAnimator()
    {
        string[] strs = Selection.assetGUIDs;
        string path = AssetDatabase.GUIDToAssetPath(strs[0]);
        Debug.Log(path);
        if(Path.GetExtension("path")!=".fbx")
        {
            Debug.LogError("not is fbx");
            return;
        }

    }

    [MenuItem("Tools/CreateFbxAnimatorController")]
    static void ProcesssFbxAnimatorController()
    {
        Object[] objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
        foreach (var x in objs)
        {
            var filePath = AssetDatabase.GetAssetPath(x);
            if (filePath.ToLower().EndsWith("fbx"))
            {
                GenerateController(filePath);
            }
        }
    }

    static void GenerateController(string fbxPath)
    {
        string fbxName = Path.GetFileNameWithoutExtension(fbxPath);
        string unitName = fbxName;
        string unitId = fbxName;
        string controllerName = unitId + "_ctr.controller";
        string controllerPath = "AnimController/" + controllerName;
        string controllerAssetPath = "Assets/" + controllerPath;
        string controllerFullPath = Application.dataPath + "/" + controllerPath;

        if (!File.Exists(controllerFullPath))
        {
            File.Copy(Application.dataPath + "/" + "AnimController/Group_Monster_Werwolf_ctr.controller", controllerFullPath);
        }
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        Dictionary<string, bool> animChecks = new Dictionary<string, bool> {
            { "Idle", false }, { "Run", false },
            { "Attack", false }, { "Skill", false },
            { "Dead", false },
            { "HurtLand",false},
        };
        if (File.Exists(controllerFullPath))
        {
            List<AnimationClip> clipList = new List<AnimationClip>();
            clipList.Clear();
            string animClipFolder = Application.dataPath + "/" + "AnimClip/" + unitId;
            if (Directory.Exists(animClipFolder))
            {
                DirectoryInfo directory = new DirectoryInfo(animClipFolder);
                FileInfo[] files = directory.GetFiles("*.anim", SearchOption.AllDirectories);

                foreach (FileInfo file in files)
                {
                    string animPath = file.ToString();
                    string animAssetPath = animPath.Substring(animPath.IndexOf("Assets"));
                    AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(animAssetPath);
                    if (clip != null)
                    {
                        if(animChecks.ContainsKey(clip.name))
                        {
                            animChecks[clip.name] = true;
                            clipList.Add(clip);
                        }
                    }
                }
            }
            bool isFull = true;
            foreach(var v in animChecks)  // 检查动作完整性
            {
                if (v.Value == false)
                {
                    isFull = false;
                }
            }
            if (!isFull)
            {
                AssetDatabase.DeleteAsset(controllerAssetPath);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
                return;
            }
            Debug.Log(controllerAssetPath);
            AnimatorController animController = AssetDatabase.LoadAssetAtPath<AnimatorController>(controllerAssetPath);
            Debug.Log(animController);
            for (int i = 0; i < animController.layers.Length; i++)
            {
                AnimatorStateMachine stateMachine = animController.layers[i].stateMachine;
                UpdateAnimator(clipList, stateMachine);
            }
        }
        else
        {
            AssetDatabase.DeleteAsset(controllerAssetPath);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
    }

    static void UpdateAnimator(List<AnimationClip> newClips, AnimatorStateMachine stateMachine)
    {
        for (int i = 0; i < stateMachine.states.Length; i++)
        {
            ChildAnimatorState childState = stateMachine.states[i];
            if (childState.state.motion == null)
            {
                if (childState.state.name.CompareTo("New State") == 0 || childState.state.name.CompareTo("empty") == 0)
                    continue;

                Debug.LogWarning(" UpdateAnimatorController Null : " + childState.state.name + ",layer name: " + stateMachine.name);
                continue;
            }
            if (childState.state.motion.GetType() == typeof(AnimationClip))
            {
                for (int j = 0; j < newClips.Count; j++)
                {
                    if (newClips[j].name.CompareTo(childState.state.motion.name) == 0)
                    {
                        childState.state.motion = (Motion)newClips[j];
                        break;
                    }
                }
            }
            else if (childState.state.motion.GetType() == typeof(UnityEditor.Animations.BlendTree))
            {

                UnityEditor.Animations.BlendTree tree = (UnityEditor.Animations.BlendTree)childState.state.motion;
                BlendTreeType treeType = tree.blendType;

                ChildMotion[] childMotionArray = tree.children;

                for (int k = 0; k < childMotionArray.Length; k++)
                {
                    if (childMotionArray[k].motion.GetType() == typeof(AnimationClip))
                    {
                        for (int j = 0; j < newClips.Count; j++)
                        {
                            if (newClips[j].name.CompareTo(childMotionArray[k].motion.name) == 0)
                            {
                                childMotionArray[k].motion = (Motion)newClips[j];
                                break;
                            }
                        }
                    }
                    else if (childMotionArray[k].motion.GetType() == typeof(UnityEditor.Animations.BlendTree))
                    {
                        Debug.LogError("You need to change it!");
                    }
                }
                tree.children = childMotionArray;
            }
        }

        for (int i = 0; i < stateMachine.stateMachines.Length; i++)
        {
            UpdateAnimator(newClips, stateMachine.stateMachines[i].stateMachine);
        }
    }

    [MenuItem("Tools/MoveCompletelyJueseAssetToCompletelyActorPath")]
    static void MoveCompletelyJueseAssetToCompletelyActorPath()
    {
        string[] strs = Selection.assetGUIDs;
        string path = AssetDatabase.GUIDToAssetPath(strs[0]);
        Debug.Log(path);
        string[] files = Directory.GetFiles(path);
        foreach (var file in files)
        {
            var modelName = Path.GetFileNameWithoutExtension(file);
            string controllerName = modelName + "_ctr.controller";
            string controllerPath = "AnimController/" + controllerName;
            string controllerFullPath = Application.dataPath + "/" + controllerPath;
            if (File.Exists(controllerFullPath))
            {
                Debug.Log(file + " to " + path + "/Actor/" + modelName + ".fbx");
                AssetDatabase.MoveAsset(file, path + "/Actor/" + modelName + ".fbx");
            }
        }
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    [MenuItem("Tools/CreateActor")]
    static void ProcessCreateActor()
    {
        var actorPath = Application.dataPath + "/ModelActor";
        if (!Directory.Exists(actorPath))
        {
            Directory.CreateDirectory(actorPath);
        }
        Object[] objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
        foreach(var obj in objs)
        {
            var assetPath = AssetDatabase.GetAssetPath(obj);
            CreateActor(assetPath);
        }
    }

    static void CreateActor(string assetPath)
    {
        var gameObject = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
        var tar = GameObject.Instantiate<GameObject>(gameObject);
        var modelName = Path.GetFileNameWithoutExtension(assetPath);
        string controllerName = modelName + "_ctr.controller";
        string assetsControllerPath = "Assets/AnimController/" + controllerName;
        string controllerPath = Application.dataPath + "/AnimController/" + controllerName;
        if (!File.Exists(controllerPath))
        {
            Debug.Log("not exists countroller " + controllerPath);
            GameObject.DestroyImmediate(tar);
            return;
        }
        var modelRoot = tar.transform.GetChild(0);
        var root = new GameObject();
        root.name = "root";
        root.transform.SetParent(tar.transform);
        var prefabPath = "Assets/ModelActor/" + modelName + ".prefab";
        modelRoot.transform.localScale = new Vector3(100, 100, 100);
        GameObject prefab = PrefabUtility.SaveAsPrefabAsset(tar, prefabPath);

        GameObject.DestroyImmediate(tar);
        prefab.tag = "Actor";
        var animator = prefab.GetComponent<Animator>();
        if (animator == null)
        {
            animator = prefab.AddComponent<Animator>();
        }
        animator.runtimeAnimatorController = AssetDatabase.LoadAssetAtPath<AnimatorController>(assetsControllerPath);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }
}
